home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!mcnc!gatech!bloom-beacon!tut.cis.ohio-state.edu!husc6!necntc!ncoast!allbery
- From: daveb@geac.UUCP (David Collier-Brown)
- Newsgroups: comp.sources.misc
- Subject: v03i018: getline -- get a long line
- Summary: an fgets with an expanding cache
- Keywords: fgets getline cache
- Message-ID: <2751@geac.UUCP>
- Date: 16 May 88 15:23:12 GMT
- Sender: allbery@ncoast.UUCP
- Reply-To: daveb@geac.UUCP (David Collier-Brown)
- Organization: Geac
- Lines: 207
- Approved: allbery@ncoast.UUCP
-
- comp.sources.misc: Volume 3, Issue 18
- Submitted-By: "David Collier-Brown" <daveb@geac.UUCP>
- Archive-Name: getline
-
- The following is a function to get a long (possibly arbitrarily
- long) line from a stream. I've written it twice, so I guess it may
- be useful to others.
- Tested ONLY on a Vax-Ultrix machine, so beware of machine
- dependencies that got by my jaundiced eye.
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: getline.c Makefile getline.1
- # Wrapped by daveb@geac on Mon May 16 11:00:49 1988
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f getline.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"getline.c\"
- else
- echo shar: Extracting \"getline.c\" \(1777 characters\)
- sed "s/^X//" >getline.c <<'END_OF_getline.c'
- X/*
- X * getline.c -- get a line into a variable-size cache. Otherwise the
- X * behavior is identical to fgets.
- X */
- X#include <stdio.h>
- X
- X#define BADEXIT 3 /* Nonzero is sufficent. 3 implies badness. */
- X#define INITIAL_CHUNK 60 /* Purely a heuristic value. */
- X#define CHUNKSIZE 10
- X
- X/*
- X * getline -- actually get the line. Behaves as expected on an eof
- X * at the beginning of a line or at end of file. Dependant on
- X * the behavior of fgets as to what happens when an EOF is entered
- X * from a terminal in the middle of a line. Under Ultrix/Berkley
- X * TTY handling, the ^D seems to disappear...
- X */
- X char *
- Xgetline(fp) FILE *fp; {
- X extern char *realloc(), *malloc();
- X extern char *lastCharacter();
- X extern void exit();
- X static char *cache = NULL;
- X static int cacheSize = 0;
- X
- X if (cache == NULL) {
- X /* Its the first time... */
- X if ((cache= malloc(INITIAL_CHUNK)) == NULL) {
- X (void) fprintf(stderr,"getline ran out of space (can't happen)\n");
- X exit(BADEXIT);
- X }
- X cacheSize = INITIAL_CHUNK;
- X }
- X
- X /* For all cases... */
- X if (fgets(cache,cacheSize,fp) == NULL) {
- X /* We hit an eof in the last line. */
- X return NULL;
- X }
- X while (*lastCharacter(cache) != '\n') {
- X /* We have to read some more... */
- X if ((cache= realloc(cache,(unsigned)cacheSize+CHUNKSIZE)) == NULL) {
- X (void) fprintf(stderr,"getline ran out of space: line longer than available memory\n");
- X exit(BADEXIT);
- X }
- X if (fgets(&cache[cacheSize-1],CHUNKSIZE+1,fp) == NULL) {
- X cacheSize += CHUNKSIZE;
- X return cache;
- X }
- X else {
- X cacheSize += CHUNKSIZE;
- X }
- X }
- X /* We've got a line ending in \n... */
- X return cache;
- X}
- X
- X
- X static char *
- XlastCharacter(p) char *p; {
- X while (p[1] != '\0')
- X p++;
- X return p;
- X }
- X
- X#ifdef TEST
- Xmain() {
- X char *p;
- X
- X while ((p=getline(stdin)) != NULL)
- X fputs(p,stdout);
- X}
- X#endif
- X
- END_OF_getline.c
- if test 1777 -ne `wc -c <getline.c`; then
- echo shar: \"getline.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f Makefile -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"Makefile\"
- else
- echo shar: Extracting \"Makefile\" \(864 characters\)
- sed "s/^X//" >Makefile <<'END_OF_Makefile'
- X#
- X# getline -- a getline to go with fgets
- X#
- X# BINDIR is where to put the executable.
- X# MANDIR is where the manual pages go, and MANEXT is the extension.
- X# for the man pages, e.g., getline.1 or getline.l or getline.m.
- X
- XBINDIR = /usr/local -- watch out!
- XMANDIR = /usr/man/manl
- XMANEXT = l
- X
- X# These should all just be right if the above ones are.
- XDIRNAME = $(BINDIR)/getline
- XDIRNAME_M = $(MANDIR)/getline.$(MANEXT)
- XLDFLAGS =
- XCFLAGS = -g -DTEST
- X
- Xgetline: getline.c
- X $(CC) $(CFLAGS) $(LDFLAGS) -o getline getline.c
- X @-size getline
- X
- Xinstall: $(DIRNAME_M)
- X
- X$(DIRNAME): getline.c
- X $(CC) $(LDFLAGS) -o getline getline.c
- X install -c -m 755 getline $(DIRNAME)
- X
- X$(DIRNAME_M): getline.1
- X cp getline.1 $(DIRNAME_M)
- X chmod 644 $(DIRNAME_M)
- X
- X
- X
- Xlint:
- X lint getline.c
- Xtags:
- X ctags -w getline.c
- Xgetline.shar:
- X shar getline.c Makefile getline.1 > getline.shar
- Xclean:
- X rm -f a.out core *.o getline
- END_OF_Makefile
- if test 864 -ne `wc -c <Makefile`; then
- echo shar: \"Makefile\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f getline.1 -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"getline.1\"
- else
- echo shar: Extracting \"getline.1\" \(873 characters\)
- sed "s/^X//" >getline.1 <<'END_OF_getline.1'
- X.TH getline 1,local
- X.SH NAME
- Xgetline \- get a line of near-arbitrary length from a stream.
- X.SH SYNTAX
- X.nf
- X#include <stdio.h>
- X
- Xchar *getline(stream)
- XFILE *stream;
- X.fi
- X
- X.SH DESCRIPTION
- XThe
- X.B getline
- Xroutine reads up to a newline character from the stream
- Xinto an internal cache of arbitrary size. The last character read
- Xis followed by a null character. The getline routine returns
- Xits first argument or NULL on end of file or error.
- X
- X.SH DIAGNOSTICS
- XIf a line longer than available memory is read, the program exits
- Xwith a message. This is expected to be a rare event.
- X
- X.SH "SEE ALSO"
- Xferror(3s), fread(3s), getc(3s), puts(3s), scanf(3s), fgets(3).
- X
- X.SH BUGS
- XStrictly dependant on the behavior of fgets: treats a ^D (eof) in
- Xmid-stream from a terminal as does fgets (ie, it disappears silently
- Xunder Ultrix/Berzerkley)
- X.PP
- XWritten by Dave (instakludge) Collier-Brown.
- END_OF_getline.1
- if test 873 -ne `wc -c <getline.1`; then
- echo shar: \"getline.1\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: End of shell archive.
- exit 0
- --
- David Collier-Brown. {mnetor yunexus utgpu}!geac!daveb
- Geac Computers Ltd., | "His Majesty made you a major
- 350 Steelcase Road, | because he believed you would
- Markham, Ontario. | know when not to obey his orders"
-